#if 0
struct control
{
    char control_name[128]; //监听模块名称
    int (*init)(void); //初始化函数
    void (*final)(void);//结束释放函数
    void *(*get)(void *arg);//监听函数， 如语音监听
    void *(*set)(void *arg); //设置函数， 如语音播报
    struct control *next;
};
#endif

#include <pthread.h>
#include <stdio.h>

#include "voice_interface.h"
#include "uartTool.h"
#include "msg_queue.h"
#include "global.h"

static int serial_fd = -1; //串口文件描述符

//初始化语音模块
//打开指定的串口设备并设置波特率
static int voice_init(void)
{
    serial_fd = myserialOpen (SERIAL_DEV, BAUD);//调用myserialOpen打开串口
    printf("%s|%s|%d:serial_fd=%d\n", __FILE__, __func__, __LINE__, serial_fd);

    return serial_fd;//返回串口文件描述符
}

//释放语音模块资源
//关闭串口连接
static void voice_final(void)
{
    if (-1 != serial_fd)
    {
        close(serial_fd);   //关闭串口
        serial_fd = -1; //重置文件描述符
    }
}


//接收语音指令
//从串口读取语音识别结果并发送到消息队列
static void *voice_get(void *arg) // mqd应该来自于arg传参
{   
    //接收缓冲区
    unsigned char buffer[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    int len = 0;        //接收数据长度
    mqd_t mqd = -1;     //消息队列描述符
    ctrl_info_t *ctrl_info= NULL;   //控制信息结构体指针

    if (NULL != arg)
        ctrl_info = (ctrl_info_t *)arg;

    //如果串口未初始化，则尝试初始化
    if (-1 == serial_fd)
    {
        serial_fd = voice_init();
        if (-1 == serial_fd)
        {
            pthread_exit(0);//初始化失败则退出线程
        }
    }

    //获取控制信息中的消息队列描述符
    if(NULL != ctrl_info)
    {
        mqd = ctrl_info->mqd;
    }

    if ((mqd_t)-1 == mqd)
    {
        pthread_exit(0);//若消息队列无效则退出线程
    }

    pthread_detach(pthread_self());//分离线程，使其结束后自动回收资源

    printf("%s thread start\n", __func__);//打印线程启动信息

    while(1){//循环读取语音指令
        len = serialGetstring(serial_fd, buffer);//从串口读取数据

        //打印接收到的数据内容
        printf("%s|%s|%d:0x%x, 0x%x,0x%x, 0x%x, 0x%x,0x%x\n",
                __FILE__, 
                __func__,
                __LINE__, 
                buffer[0], 
                buffer[1], 
                buffer[2], 
                buffer[3], 
                buffer[4],
                buffer[5]);

        printf("%s|%s|%d:len=%d\n", __FILE__, __func__, __LINE__, len);

        if(len > 0){//如果成功读取到数据
            //判断数据帧格式是否正确
            if(buffer[0] == 0xAA && buffer[1] == 0x55 && buffer[5] == 0xAA && buffer[4] == 0x55){
                //打印有效的语音指令数据
                printf("%s|%s|%d:send 0x%x, 0x%x,0x%x, 0x%x, 0x%x,0x%x\n", 
                    __FILE__, 
                    __func__, 
                    __LINE__, 
                    buffer[0], 
                    buffer[1], 
                    buffer[2], 
                    buffer[3],
                    buffer[4],
                    buffer[5]);

                //将语音指令发送到消息队列
                send_message(mqd, buffer, len);//注意，不要用strlen去计算实际的长度
            }
            memset(buffer, 0, sizeof(buffer));//清空缓冲区
        }
    }

    pthread_exit(0);//线程正常退出
}

//语音播报功能，向串口发送语音播报指令
static void *voice_set(void *arg)
{
    pthread_detach( pthread_self() );//分离线程，使其结束后自动回收资源
    unsigned char *buffer = (unsigned char *)arg;//获取要播报的数据

    //如果串口未初始化，则尝试初始化
    if (-1 == serial_fd)
    {
        serial_fd = voice_init();
        if (-1 == serial_fd)
        {
            pthread_exit(0);//初始化失败则退出线程
        }
    } 
    
    //如果数据缓冲区不为空，则发送语音播报指令
    if (NULL != buffer)
    {
        serialSendstring(serial_fd, buffer, 6);//向串口发送6个字节数据
    } 

    pthread_exit(0);    //线程正常退出
}

//定义语音控制模块实例
struct control voice_control = {
    .control_name = "voice",    //控制模块名称
    .init = voice_init,         //初始化函数
    .final = voice_final,       //结束函数
    .get = voice_get,           //数据接收函数（线程主函数）
    .set = voice_set,           //设置函数（语音播报）
    .next = NULL                //链表指针
};

//将语音控制模块添加到全局控制的链表中
struct control *add_voice_to_ctrl_list(struct control *phead)
{
    //使用头插法将语音控制模块插入到链表中
    return add_interface_to_ctrl_list(phead, &voice_control);
}